今天是第二十二天我們可以寫一個k8s選課資料庫管理系統,以下是我的程式碼
創建一個 mysql-deployment.yaml
檔案來部署 MySQL。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
- name: MYSQL_DATABASE
value: "course_db"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_PASSWORD
value: "password"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
創建一個簡單的 Flask API,與 MySQL 互動。首先,撰寫 app.py
:
from flask import Flask, request, jsonify
import mysql.connector
app = Flask(__name__)
def get_db_connection():
conn = mysql.connector.connect(
host='mysql', # Kubernetes 服務名稱
user='admin',
password='password',
database='course_db'
)
return conn
@app.route('/courses', methods=['GET'])
def get_courses():
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM courses')
courses = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(courses)
@app.route('/enroll', methods=['POST'])
def enroll_course():
student_id = request.json['student_id']
course_id = request.json['course_id']
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('INSERT INTO enrollments (student_id, course_id) VALUES (%s, %s)', (student_id, course_id))
conn.commit()
cursor.close()
conn.close()
return 'Enrolled successfully!', 201
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
創建 Dockerfile
來打包 Flask API:
FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
requirements.txt
:
Flask
mysql-connector-python
接著,創建 flask-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-api
spec:
selector:
matchLabels:
app: flask-api
template:
metadata:
labels:
app: flask-api
spec:
containers:
- name: flask-api
image: your-dockerhub-username/flask-api:latest
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: flask-api
spec:
ports:
- port: 5000
selector:
app: flask-api
創建一個簡單的 index.html
:
<!DOCTYPE html>
<html>
<head>
<title>選課系統</title>
</head>
<body>
<h1>選課系統</h1>
<form id="enrollForm">
學生 ID: <input type="text" id="student_id"><br><br>
課程 ID: <input type="text" id="course_id"><br><br>
<button type="submit">選課</button>
</form>
<h2>已選課程</h2>
<ul id="coursesList"></ul>
<script>
document.getElementById('enrollForm').onsubmit = function(event) {
event.preventDefault();
const studentId = document.getElementById('student_id').value;
const courseId = document.getElementById('course_id').value;
fetch('/enroll', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ student_id: studentId, course_id: courseId })
})
.then(response => response.text())
.then(data => alert(data));
};
fetch('/courses')
.then(response => response.json())
.then(courses => {
const coursesList = document.getElementById('coursesList');
courses.forEach(course => {
const li = document.createElement('li');
li.textContent = `課程 ID: ${course[0]}, 課程名稱: ${course[1]}`;
coursesList.appendChild(li);
});
});
</script>
</body>
</html>
將此前端部署在 Nginx 上,並創建 nginx-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: frontend-html
---
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-html
data:
index.html: |
# (Paste index.html content here)
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
ports:
- port: 80
selector:
app: frontend
運行以下指令將部署所有服務:
kubectl apply -f mysql-deployment.yaml
kubectl apply -f flask-deployment.yaml
kubectl apply -f nginx-deployment.yaml
這樣,Kubernetes 就會運行選課系統,前端透過 Nginx 提供服務,後端 Flask API 處理選課請求,並與 MySQL 進行互動。
在 mysql-deployment.yaml
中,定義了 MySQL 資料庫的 Kubernetes 資源。這裡主要包含以下幾個部分:
這段程式碼是用來申請一塊持久性存儲空間,用於 MySQL 存儲資料。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
PersistentVolumeClaim
(PVC):它用來請求一塊 10GB 的持久存儲。這塊存儲將會被用來保存 MySQL 資料庫的數據,即使 Pod 被重啟,數據也不會丟失。accessModes
:設置為 ReadWriteOnce
,表示這塊存儲可以被一個節點讀寫。MySQL 被打包成一個容器,這裡通過 Deployment
創建和管理 MySQL Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
- name: MYSQL_DATABASE
value: "course_db"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_PASSWORD
value: "password"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
Deployment
:定義了 MySQL 容器的部署,管理 MySQL 的 Pod。image: mysql:5.7
:指定 MySQL 的 Docker 鏡像版本。env
:環境變量,用來設定 MySQL 的 root 密碼、資料庫名稱以及用戶憑證。volumeMounts
:將 PVC 持久化存儲掛載到容器內 /var/lib/mysql
目錄,這是 MySQL 存放數據的地方。apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
Service
:定義了如何對外暴露 MySQL 服務,讓其他 Pod(如 Flask API)可以通過 Kubernetes 的內部 DNS 名稱(mysql
)來訪問資料庫。port: 3306
:指定 MySQL 使用的默認端口。Flask API 是一個簡單的應用,它用來與 MySQL 資料庫互動,處理選課相關的操作。
from flask import Flask, request, jsonify
import mysql.connector
app = Flask(__name__)
Flask
:引入 Flask 框架來處理 HTTP 請求。mysql.connector
:用來與 MySQL 資料庫連接。app = Flask(__name__)
:初始化 Flask 應用,並且可以設定各種路由。def get_db_connection():
conn = mysql.connector.connect(
host='mysql', # Kubernetes 服務名稱
user='admin',
password='password',
database='course_db'
)
return conn
get_db_connection()
:用來建立與 MySQL 資料庫的連接。host='mysql'
表示 MySQL 是通過 Kubernetes 的內部 DNS 名稱來訪問。user
、password
、database
:與 MySQL 連接所需的憑證。@app.route('/courses', methods=['GET'])
def get_courses():
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM courses')
courses = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(courses)
@app.route('/courses', methods=['GET'])
:定義了一個 GET 請求的 API,URL 是 /courses
。這個 API 會查詢所有課程。cursor.execute('SELECT * FROM courses')
:從 courses
資料表中查詢所有課程。jsonify(courses)
:將查詢結果轉換成 JSON 格式,回傳給客戶端。@app.route('/enroll', methods=['POST'])
def enroll_course():
student_id = request.json['student_id']
course_id = request.json['course_id']
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('INSERT INTO enrollments (student_id, course_id) VALUES (%s, %s)', (student_id, course_id))
conn.commit()
cursor.close()
conn.close()
return 'Enrolled successfully!', 201
@app.route('/enroll', methods=['POST'])
:定義了一個 POST 請求的 API,URL 是 /enroll
。這個 API 用來讓學生選課。student_id
和 course_id
:從請求中提取學生和課程的 ID。INSERT INTO enrollments (student_id, course_id)
:將選課資訊插入到 enrollments
資料表中。前端是一個簡單的 HTML 頁面,通過 JavaScript 與 Flask API 互動。
<form id="enrollForm">
學生 ID: <input type="text" id="student_id"><br><br>
課程 ID: <input type="text" id="course_id"><br><br>
<button type="submit">選課</button>
</form>
document.getElementById('enrollForm').onsubmit = function(event) {
event.preventDefault();
const studentId = document.getElementById('student_id').value;
const courseId = document.getElementById('course_id').value;
fetch('/enroll', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ student_id: studentId, course_id: courseId })
})
.then(response => response.text())
.then(data => alert(data));
};
onsubmit
:攔截表單的提交動作。fetch('/enroll', ...)
:向 /enroll
API 發送 POST 請求,將選課資訊發送到伺服器。JSON.stringify()
:將 JavaScript 對象轉換為 JSON 格式,發送至後端。fetch('/courses')
.then(response => response.json())
.then(courses => {
const coursesList = document.getElementById('coursesList');
courses.forEach(course => {
const li = document.createElement('li');
li.textContent = `課程 ID: ${course[0]}, 課程名稱: ${course[1]}`;
coursesList.appendChild(li);
});
});
fetch('/courses')
:向 /courses
API 發送 GET 請求,取得所有課程。前端的 HTML 和 JavaScript 被 Nginx 提供服務。
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: frontend-html
---
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-html
data:
index.html: |
<!-- HTML 文件內容 -->
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
ports:
- port: 80
selector:
app: frontend
nginx
:用來提供靜態 HTML 文件服務。ConfigMap
:將 index.html
內容儲存在 ConfigMap 中,並掛載到 Nginx 容器的 /usr/share/nginx/html
目錄下。Service
:對外暴露 Nginx 服務,使用默認的 HTTP 端口 80。這個系統是一個簡單的選課系統,前端通過 Nginx 提供靜態頁面服務,後端 Flask API 用來處理資料庫操作,MySQL 資料庫存放課程和選課信息。每個部分都通過 Kubernetes 來管理和調度,使應用能夠在容器化環境中運行。